package com.tencent.sr.iris.basic.saas.service.asynctask.activity;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Maps;
import com.tencent.sr.iris.activity.interfaces.request.IrisPaginationRequest;
import com.tencent.sr.iris.baisc.saas.export.sdk.BaseExportTask;
import com.tencent.sr.iris.baisc.saas.export.sdk.ScrollRequest;
import com.tencent.sr.iris.baisc.saas.export.sdk.ScrollResponse;
import com.tencent.sr.iris.baisc.saas.export.sdk.TaskContextHolder;
import com.tencent.sr.iris.basic.saas.interfaces.request.activity.ActivityTaskPageRequest;
import com.tencent.sr.iris.basic.saas.interfaces.response.activity.ActivityTaskPageResponse;
import com.tencent.sr.iris.basic.saas.service.activity.ActivityTaskService;
import com.tencent.sr.iris.basic.saas.service.convert.OrgConvert;
import com.tencent.sr.iris.basic.saas.service.dependency.OrganManagerDependency;
import com.tencent.sr.iris.basic.saas.service.model.activity.BaseActivityTaskExportInfo;
import com.tencent.sr.iris.basic.saas.service.util.ActivityExportUtils;
import com.tencent.sr.iris.user.core.service.interfaces.response.organ.IrisOrganTreeItem;
import com.tencent.sr.rmall.common.response.PaginationResponse;
import com.tencent.sr.rmall.material.interfaces.enums.ETaskBusinessType;
import com.tencent.sr.rmall.material.interfaces.response.TaskRecordResponse;
import com.tencent.sr.rmall.springbootstarter.elasticjob.TaskJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@Component
@TaskJob(jobName = "iris:export:ActivityDetailExportTask", cron = "0/5 * * * * ? ", description = "活动明细导出任务")
public class ActivityDetailExportTask extends BaseExportTask<ActivityTaskPageRequest, BaseActivityTaskExportInfo> {

    private static ThreadLocal<AtomicInteger> lineNum = ThreadLocal.withInitial(AtomicInteger::new);
    private final int maxLines = 1000000;
    private final int pageSize = 50;

    /**
     * 区域缓存
     */
    private LoadingCache<String, Map<Long, String>> areaCache = CacheBuilder.newBuilder()
            //设置并发级别为8，并发级别是指可以同时写缓存的线程数
            .concurrencyLevel(8)
            //设置缓存容器的初始容量为10
            .initialCapacity(10)
            //设置缓存最大容量为100，超过100之后就会按照LRU最近虽少使用算法来移除缓存项
            .maximumSize(100)
            //设置写缓存后n秒钟过期
            .expireAfterWrite(30, TimeUnit.MINUTES)
            //build方法中可以指定CacheLoader，在缓存不存在时通过CacheLoader的实现自动加载缓存
            .build(new CacheLoader<String, Map<Long, String>>() {
                @Override
                public Map<Long, String> load(String key) {
                    return getOrgMap();
                }
            });
    @Resource
    private ActivityTaskService activityTaskService;

    @Resource
    private OrganManagerDependency organManagerDependency;

    /**
     * 获取地区map
     * @return
     */
    public Map<Long, String> getOrgMap() {
        List<IrisOrganTreeItem> organTree = organManagerDependency.queryOrganTree();
        return OrgConvert.getOrgMap(organTree);
    }

    @Override
    public ScrollResponse<BaseActivityTaskExportInfo> get(ScrollRequest<ActivityTaskPageRequest> scrollRequest) {
        TaskRecordResponse taskRecord = TaskContextHolder.get();
        log.info("ActivityDetailExportTask taskRecord: {}, request: {}", taskRecord, scrollRequest);
        ScrollResponse<BaseActivityTaskExportInfo> result = new ScrollResponse<>();
        // 判断是否已经达到文件行数上限
        AtomicInteger num = lineNum.get();
        if (num.get() >= maxLines) {
            lineNum.set(new AtomicInteger());
            return result;
        }
        IrisPaginationRequest<ActivityTaskPageRequest> paginationRequest = new IrisPaginationRequest<>();
        ActivityTaskPageRequest queryCriteria = scrollRequest.getQueryCriteria();
        queryCriteria.setCurrentUserUid(taskRecord.getOperatorId())
                .setCurrentUserSaaSId(taskRecord.getSaasId());
        paginationRequest.setQueryCriteria(queryCriteria);
        int pageNum = (num.get()) / pageSize + 1;
        paginationRequest.setPageNum(pageNum);
        paginationRequest.setPageSize(pageSize);

        String activityType = queryCriteria.getActivityType();
        String activityId = queryCriteria.getActivityId();

        PaginationResponse<ActivityTaskPageResponse> response = activityTaskService.page(paginationRequest);
        log.info("ActivityDetailExportTask response:{}", response);

        List<BaseActivityTaskExportInfo> exportInfoList = new ArrayList<>();
        this.getExportClass().set(ActivityExportUtils.getExportClass(activityType, activityId));

        List<ActivityTaskPageResponse> dataList = response.getDataList();
        if (CollUtil.isNotEmpty(dataList)) {
            boolean multiTask = dataList.get(0).getMultiTask();
            if (multiTask) {
                ActivityTaskPageResponse after = dataList.stream()
                        .max(Comparator.comparing(ActivityTaskPageResponse::getUid))
                        .orElseGet(ActivityTaskPageResponse::new);
                queryCriteria.setSearchAfter(after.getUid());
            }

            for (ActivityTaskPageResponse taskPageResponse : dataList) {
                BaseActivityTaskExportInfo exportInfo = ActivityExportUtils.newExportEntity(activityType, activityId);

                Map<Long, String> map = null;
                try {
                    map = areaCache.get(StrUtil.EMPTY);
                } catch (Exception e) {
                    log.error("ActivityDetailExportTask查询区域信息失败：", e);
                }
                map = Optional.ofNullable(map).orElseGet(Maps::newHashMap);
                // 数据转换
                exportInfo.readFromSearchResponseData(taskPageResponse, map);
                // 设置行号
                exportInfo.setNum(num.incrementAndGet());
                exportInfoList.add(exportInfo);
                // 最多支持5000条商品数据导出
                if (num.get() >= maxLines) {
                    break;
                }
            }
            result.setDataList(exportInfoList);
            // 最后一页
            if (response.getDataList().size() < pageSize) {
                num.addAndGet(pageSize - response.getDataList().size());
            }
        } else {
            lineNum.set(new AtomicInteger());
        }
        result.setScrollId(String.valueOf(System.currentTimeMillis()) + exportInfoList.size());
        log.info("ActivityDetailExportTask result:{}", result);
        return result;
    }

    @Override
    public String exportType() {
        return ETaskBusinessType.IRIS_ACTIVITY_TASK_DETAIL.name();
    }
}
